# Именование программных компонентов

Мы именуем программные компоненты следующим образом:

### Пакеты

Пакеты именуются как можно более односложно.
Например: `controller`, `client`, `service`, `util`.
Если пакет необходимо именовать несколькими словами, возможно, архитектура спроектирована неправильно.
Возможно, можно сгруппировать несколько пакетов в один общий пакет.
Если всё-таки необходимо использовать несколько слов в имени пакета, мы используем `snake_case`.

### Классы

#### Сущности (data-классы)

В наименовании сущности используется существительное и только.
Например: `User`, `Contact`, `Order`.
К именам сущностей DAO добавляется постфикс, раскрывающий их суть более подробно.
Для репозиторных сущностей: `UserEntity`, `OrderTable`.
Для моделей контроллера: `UserRequest`, `UserResponse`.

#### Поведенческие классы (интерфейсы, их наследники)

Интерфейсы контрактуют поведение приложения.
При именовании интерфейсов мы используем наименования сущности, с которой они работают, и отглагольные существительные, раскрывающие суть поведения класса.
Например: `UserService`, `MigrationController`, `OrderProcessor`.

Для наследников, мы добавляем к наименованию родительского класса постфикс, описывающий конкретную реализацию.
Например: `UserServiceImpl`, `OrderProcessorMock`, `ExceptionHandlerRest`.

В случае, если отличие основано на бизнес-сущности, мы добавляем префикс перед наименованием родительского интерфейса.
Например:
`UserProcessor`, `OrderProcessor`, `ContactProcessor`.

Когда дело касается абстрактного класса, мы добавляем префикс `Abstract` перед полным названием класса (после добавления префикса бизнес-сущности):
`AbstractUserProcessor`, `AbstractOrderHandler`.

Если поведенческий класс работает с несколькими сущностями, его надо перепроектировать таким образом, чтобы он работал с одной.

### Функции

При именовании функций используются глаголы.
Глагол должен точно объяснять, что происходит внутри функции.
Например: `getUser`, `setOrder`, `deleteProfile`.

Глагол не может быть абстрактным, например: `processUser`, `interactWithOrder`, `handleProfile`.
Если невозможно использовать для именования функции понятный глагол, значит, функция была спроектирована неправильно, и её нужно перепроектировать таким образом, чтобы она делала что-то одно понятное.

### Поля

Если поля являются свойствами класса, для их именования мы используем существительное.
Имя поля должно как можно более точно и просто объяснять, что оно делает.
Мы упрощаем имя, если контекст или тип класса сохраняет имя понятным.
Например: `group: UserGroup`, `status: OrderStatus`, `name: String`.

Если тип поля является поведенческим классом, мы используем полное имя класса в имени поля.
Например: `userService: UserService`, `orderRepository: OrderRepository`.

Мы упрощаем название поля, если из контекста понятен его тип.
Например, `service: UserService` для `UserController`, `repository: OrderRepository` для `OrderService`.

### Внутренние переменные

Имя внутренней переменной должно точно передавать то, что она хранит в себе.
Если для двух и более локальных переменных напрашивается одно наименование, то, скорее всего, у вас проблемы с проектированием функции.

---

### Использование контекста при именовании программных компонентов

Если название компонента можно упростить так, чтобы его замысел был понятен из контекста, мы этим пользуемся.

Примеры:

Для поведенческих классов: если мы инициализируем `UserService` в `UserController`, его достаточно назвать `service`.

Для функций: если в классе `User` имеется функция-геттер, её не нужно называть `getUser`, достаточно назвать её `get` - из контекста будет понятно, что это геттер для класса `User`.